<template>
  <div ref="canvas"></div>
</template>

<script lang="ts" setup>
import * as THREE from "three";
import Stats from "three/examples/jsm/libs/stats.module";
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls";
import { GUI } from "three/examples/jsm/libs/lil-gui.module.min.js";
import { ref, onMounted } from "vue";

const canvas = ref();

const scene = new THREE.Scene();
// 渲染器
const renderer = new THREE.WebGLRenderer({ antialias : true });
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setClearColor(0x000000);
renderer.shadowMap.enabled = true;
renderer.shadowMap.type = THREE.PCFSoftShadowMap;
// 相机
const camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 2000);
camera.position.set(40, 10, 150);
camera.lookAt(20, 30, 0);
// 相机控件
const orbitControl = new OrbitControls(camera, renderer.domElement);
orbitControl.update();
// 性能统计
const stat = Stats();

// sprites
const createSprites = (): THREE.Group => {
  const group = new THREE.Group();

  const range = 200;
  for (let i = 0; i < 400; i++) {
    group.add(createSprite(10, false, 0.6, 0xffffff, i % 5, range));
  }

  return group;
};
const createSprite = (size, transparent, opacity, color, spriteNumber, range): THREE.Sprite => {
  const texture = new THREE.TextureLoader().load(new URL("@/assets/textures/particles/sprite-sheet.png", import.meta.url).href);
  const spriteMaterial = new THREE.SpriteMaterial({
    opacity: opacity,
    color: color,
    transparent: transparent,
    map: texture,
  });

  spriteMaterial.map.offset = new THREE.Vector2(0.2 * spriteNumber, 0);
  spriteMaterial.map.repeat = new THREE.Vector2(1 / 5, 1);
  spriteMaterial.depthTest = false;
  spriteMaterial.blending = THREE.AdditiveBlending;

  const sprite = new THREE.Sprite(spriteMaterial);
  sprite.scale.set(size, size, size);
  sprite.position.set(
      Math.random() * range - range / 2,
      Math.random() * range - range / 2,
      Math.random() * range - range / 2);

  return sprite;
};

const group = createSprites();
scene.add(group);

const render = () => {
  stat.update();

  group.rotation.x += 0.005;
  group.rotation.y += 0.005;
  group.rotation.z += 0.005;

  requestAnimationFrame(render);
  renderer.render(scene, camera);
};

onMounted(() => {
  canvas.value.appendChild(stat.domElement);
  canvas.value.appendChild(renderer.domElement);

  render();
});

</script>
